.text
.globl idt, gdt, pg_dir, tmp_floppy_area
pg_dir:
.globl startup_32
startup_32:
    movl    $0x10, %eax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    lss stack_start, %esp
    call setup_idt
    call setup_gdt
    movl    $0x10, %eax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    lss stack_start, %esp
    xorl    %eax, %eax
1:  incl    %eax        # 检查是否开启A20
    movl    %eax, 0x0
    cmpl    %eax, 0x100000
    je 1b

    jmp after_page_tables

setup_idt:
    lidt    idt_descr
    ret

setup_gdt:
    lgdt    gdt_descr
    ret

.org    0x1000
pg0:

.org    0x2000
pg1:

.org    0x3000
pg2:

.org    0x4000
pg3:

.org    0x5000

tmp_floppy_area:
    .fill   1024, 1, 0

after_page_tables:
    pushl   $0
    pushl   $0
    pushl   $0
    pushl   $L6     # 设置main函数的返回地址
    pushl   $main   # 设置setup_paging的返回地址为main函数
    jmp setup_paging
L6: jmp L6

.align  4
setup_paging:
    movl    1024 * 5, %ecx
    xorl    %eax, %eax
    xorl    %edi, %edi
    cld
    rep
    stosl
    movl    $pg0 + 7, pg_dir
    movl    $pg1 + 7, pg_dir + 4
    movl    $pg2 + 7, pg_dir + 8
    movl    $pg3 + 7, pg_dir + 12   # 在页目录中设置页表信息
    movl    $pg0, %edi
    movl    $0x0007, %eax
1:  stosl
    addl    $0x1000, %eax
    cmpl    $0x1000007, %eax
    jne 1b                  # 设置页信息
    xorl    %eax, %eax
    movl    %eax, %cr3
    movl    %cr0, %eax
    orl $0x80000000, %eax
    movl    %eax, %cr0      # 设置CR0的PG位，开启分页
    ret

.align  4
.word   0
idt_descr:
    .word   256 * 8 - 1
    .long   idt

.align  4
.word   0
gdt_descr:
    .word   256 * 8 - 1
    .long   gdt

.align  8
idt:.fill   256, 8, 0

gdt:.quad   0x0000000000000000
    .quad   0x00c09a0000000fff
    .quad   0x00c0920000000fff
    .quad   0x0000000000000000
    .fill   252, 8, 0
